package cn.shengchao.examstar.product.acl.adapters.repositories;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.shengchao.examstar.product.acl.ports.repositories.IProductCourseSettingRepository;
import cn.shengchao.examstar.product.domain.entity.CourseKnowledgeNode;
import cn.shengchao.examstar.product.domain.entity.Product;
import cn.shengchao.examstar.product.infrastructure.dao.TProductCourseSettingDao;
import cn.shengchao.examstar.product.infrastructure.dao.po.TProductCourseNodes;
import cn.shengchao.examstar.product.infrastructure.dao.po.TProductCourseSetting;
import cn.shengchao.examstar.rpc.base.TransResult;
import cn.shengchao.examstar.rpc.orders.res.PayOrderInfoDto;
import cn.shengchao.examstar.rpc.orders.res.PayOrderItemInfoDto;
import cn.shengchao.examstar.rpc.product.base.ContentProductTypeDefine;
import cn.shengchao.examstar.rpc.product.base.ProductPropertyDto;
import cn.shengchao.examstar.rpc.product.base.ProductSettingDto;
import cn.shengchao.examstar.rpc.product.req.ProductCourseSettingBatchSaveDto;
import cn.shengchao.examstar.rpc.product.req.ProductCourseSettingDeleteDto;
import cn.shengchao.examstar.rpc.product.req.ProductCourseSettingDto;
import cn.shengchao.examstar.rpc.product.req.ProductCourseSettingPageQuery;
import cn.shengchao.examstar.rpc.product.res.ProductCourseSettingVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @program: examstarapi
 * @description: 产品合作配置
 * @author: Xiong weiqiang
 * @create: 2025-06-27 20:11
 */
@Service
public class ProductCourseSettingRepository extends ServiceImpl<TProductCourseSettingDao, TProductCourseSetting>  implements IProductCourseSettingRepository {
    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Override
    public TransResult<String> saveProductCourseSettingForGkCourse(ProductCourseSettingBatchSaveDto productCourseSettingBatchSaveDto) {
        String lockKey="PRODUCT_COURSE_GK_BATCH_INSERT";
        try {
            if (redisTemplate.hasKey(lockKey)) {
                redisTemplate.opsForValue().set(lockKey, 1);
//                long count =getBaseMapper().countGanKaoProductValidPeriod(productCourseSettingBatchSaveDto.getCorpStartTime(),productCourseSettingBatchSaveDto.getCorpEndTime());
//                if (count>0){
//                    return TransResult.fail("赶考课程配置该时间段内已存在课程合作配置，区间不能重叠");
//                }
                List<TProductCourseSetting> productCourseSettings = baseMapper
                        .selectList(Wrappers.lambdaQuery(TProductCourseSetting.class).eq(TProductCourseSetting::getProductType, ContentProductTypeDefine.COURSE_GK.name()).orderByDesc(TProductCourseSetting::getId));
                baseMapper.update(Wrappers.lambdaUpdate(TProductCourseSetting.class).eq(TProductCourseSetting::getProductType, ContentProductTypeDefine.COURSE_GK.name()).set(TProductCourseSetting::getDataStatus,2));
                Map<Long, TProductCourseSetting> productCourseSettingMap = productCourseSettings.stream().collect(Collectors.toMap(TProductCourseSetting::getProductId, Function.identity(), (old, current) -> old));
                List<Long> productIds = productCourseSettings.stream().map(TProductCourseSetting::getProductId).distinct().toList();

                int size=70;
                int loadSize=0;
                List< CompletableFuture<Void>> futureList=new ArrayList<>();
                while (loadSize<productIds.size()){
                    int loadIndex=loadSize+size;
                    List<Long> gkCourseSubList=productIds.subList(loadSize, Math.min(loadIndex, productIds.size()));
                    loadSize=loadIndex;
                    futureList.add(CompletableFuture.runAsync(()->{
                        List<TProductCourseSetting> productCourseSettingSaveList = new ArrayList<>();
                        gkCourseSubList.forEach(gkCourseId -> {
                            TProductCourseSetting tProductCourseSetting = productCourseSettingMap.get(gkCourseId);
                            String refThirdId = tProductCourseSetting.getRefThirdId();
                            String productType = tProductCourseSetting.getProductType();
                            tProductCourseSetting.setProductType(productType);
                            tProductCourseSetting.setProductId(tProductCourseSetting.getProductId());
                            tProductCourseSetting.setCorpStartTime(productCourseSettingBatchSaveDto.getCorpStartTime());
                            tProductCourseSetting.setCorpEndTime(productCourseSettingBatchSaveDto.getCorpEndTime());
                            tProductCourseSetting.setUnitPayDay(productCourseSettingBatchSaveDto.getUnitPayDay());
                            tProductCourseSetting.setRefThirdId(refThirdId);
                            tProductCourseSetting.setBatchId(productCourseSettingBatchSaveDto.getBatchId());
                            tProductCourseSetting.setDataStatus(1);
                            productCourseSettingSaveList.add(tProductCourseSetting);
                        });
                        saveBatch(productCourseSettingSaveList);
                    }));
                }
                CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
            }
        }finally {
            redisTemplate.delete(lockKey);
        }
        return TransResult.success("成功");
    }

    @Transactional
    @Override
    public TransResult<String> saveProductCourseSettingByCourse(ProductCourseSettingBatchSaveDto productCourseSettingBatchSaveDto) {
        Set<Long> knowledgeIds=new HashSet<>();
        if ("COURSE".equals(productCourseSettingBatchSaveDto.getParentType())){
            List<CourseKnowledgeNode> knowledgeNodes =productRepository.findListByCourseId(productCourseSettingBatchSaveDto.getParentId(),null, true);
            List<ProductCourseSettingVo> list=queryForCourse(productCourseSettingBatchSaveDto.getParentId());
            if (CollUtil.isNotEmpty(list)) {
                baseMapper.update(Wrappers.lambdaUpdate(TProductCourseSetting.class).in(TProductCourseSetting::getProductId, list.stream().map(ProductCourseSettingVo::getProductId).toList()).set(TProductCourseSetting::getDataStatus,2));

//                for (ProductCourseSettingVo productCourseSettingVo : list) {
//                    if (productCourseSettingVo.getCorpStartTime().after(productCourseSettingBatchSaveDto.getCorpStartTime())||productCourseSettingVo.getCorpEndTime().before(productCourseSettingBatchSaveDto.getCorpEndTime())){
//                        return TransResult.fail("课程配置该时间段内已存在课程合作配置，区间不能重叠");
//                    }
//                }
            }
            if (CollUtil.isNotEmpty(knowledgeNodes)){
                knowledgeIds.addAll(knowledgeNodes.stream().map(Product::getId).collect(Collectors.toSet()));
            }
        }else{
            //课程节点
            List<Long> sectionIds=productRepository.findCourseNodesByParentLessonId(productCourseSettingBatchSaveDto.getParentId());
            List<ProductCourseSettingVo> list=new ArrayList<>();
            if (CollUtil.isNotEmpty(sectionIds)){
                list=queryForLesson(productCourseSettingBatchSaveDto.getParentId(),sectionIds);
            }
            if (CollUtil.isNotEmpty(list)) {
                baseMapper.update(Wrappers.lambdaUpdate(TProductCourseSetting.class).in(TProductCourseSetting::getProductId, list.stream().map(ProductCourseSettingVo::getProductId).toList()).set(TProductCourseSetting::getDataStatus,2));
//                for (ProductCourseSettingVo productCourseSettingVo : list) {
//                    if (productCourseSettingVo.getCorpStartTime().after(productCourseSettingBatchSaveDto.getCorpStartTime())||productCourseSettingVo.getCorpEndTime().before(productCourseSettingBatchSaveDto.getCorpEndTime())){
//                        return TransResult.fail("章节配置该时间段内已存在课程合作配置，区间不能重叠");
//                    }
//                }
            }
            if (CollUtil.isNotEmpty(sectionIds)) {
                //课程节点
                List<TProductCourseNodes> courseKnowledgeNodeLessons = productRepository.findCourseNodesByProductIds(sectionIds, true);
                if (CollUtil.isNotEmpty(courseKnowledgeNodeLessons)) {
                    knowledgeIds.addAll(courseKnowledgeNodeLessons.stream().map(TProductCourseNodes::getId).collect(Collectors.toSet()));
                }
            }
        }
//        Map<Long, CourseKnowledgeNode> courseKnowledgeNodeMap=knowledgeNodes.stream().collect(Collectors.toMap(Product::getId, Function.identity()));
        if (CollUtil.isNotEmpty(knowledgeIds)){
            List<TProductCourseSetting> productCourseSettings=baseMapper
                    .selectList(Wrappers.lambdaQuery(TProductCourseSetting.class).in(TProductCourseSetting::getProductId,knowledgeIds).orderByDesc(TProductCourseSetting::getId));
            Map<Long,TProductCourseSetting> productCourseSettingMap=productCourseSettings.stream().collect(Collectors.toMap(TProductCourseSetting::getProductId, Function.identity(),(old,current)->old));
            List<TProductCourseSetting> productCourseSettingSaveList=new ArrayList<>();
            for (Long courseNodeId: knowledgeIds){
                TProductCourseSetting tProductCourseSetting=productCourseSettingMap.get(courseNodeId);
                TProductCourseSetting tProductCourseSettingSave=new TProductCourseSetting();
                String refThirdId=null;
                String productType=null;
                if (tProductCourseSetting==null){
                    productType= ContentProductTypeDefine.COURSE.name();
                    refThirdId = courseNodeId.toString();
                }else{
                    //赶考的默认手动配置过了，不然也找不到它那边的课程配置id
                    refThirdId = tProductCourseSetting.getRefThirdId();
                    productType= tProductCourseSetting.getProductType();
                }
                tProductCourseSettingSave.setProductType(productType);
                tProductCourseSettingSave.setProductId(courseNodeId);
                tProductCourseSettingSave.setCorpStartTime(productCourseSettingBatchSaveDto.getCorpStartTime());
                tProductCourseSettingSave.setCorpEndTime(productCourseSettingBatchSaveDto.getCorpEndTime());
                tProductCourseSettingSave.setUnitPayDay(productCourseSettingBatchSaveDto.getUnitPayDay());
                tProductCourseSettingSave.setRefThirdId(refThirdId);
                tProductCourseSettingSave.setDataStatus(1);
                tProductCourseSettingSave.setBatchId(productCourseSettingBatchSaveDto.getBatchId());
                productCourseSettingSaveList.add(tProductCourseSettingSave);
            }
            saveBatch(productCourseSettingSaveList);
        }
        return TransResult.success("成功");
    }


    @Override
    public TransResult<String> saveProductCourseSetting(ProductCourseSettingDto productCourseSettingDto) {
        String refThirdId=null;
        String productType=null;
//        if (getBaseMapper().countProductValidPeriod(productCourseSettingDto.getProductId(),productCourseSettingDto.getCorpStartTime(),productCourseSettingDto.getCorpEndTime())>0){
//            return TransResult.fail("单个产品设置存在区间重复");
//        }
        baseMapper.update(Wrappers.lambdaUpdate(TProductCourseSetting.class).eq(TProductCourseSetting::getProductId, productCourseSettingDto.getProductId()).set(TProductCourseSetting::getDataStatus,2));

        List<TProductCourseSetting> productCourseSettings=baseMapper.selectList(Wrappers.lambdaQuery(TProductCourseSetting.class).eq(TProductCourseSetting::getProductId,productCourseSettingDto.getProductId()).orderByDesc(TProductCourseSetting::getId));
        if (CollUtil.isNotEmpty(productCourseSettings)){
                refThirdId = productCourseSettings.getFirst().getRefThirdId();
                productType= productCourseSettings.getFirst().getProductType();
            }else {
                productType= ContentProductTypeDefine.COURSE.name();
        }
        TProductCourseSetting tProductCourseSetting=new TProductCourseSetting();
        BeanUtil.copyProperties(productCourseSettingDto,tProductCourseSetting);
        tProductCourseSetting.setRefThirdId(refThirdId);
        tProductCourseSetting.setProductType(productType);
        tProductCourseSetting.setUnitPayDay(productCourseSettingDto.getUnitPayDay());
        tProductCourseSetting.setDataStatus(1);
        tProductCourseSetting.setBatchId(System.currentTimeMillis());
        baseMapper.insert(tProductCourseSetting);
        return TransResult.success("配置成功");
    }

    @Override
    public List<ProductCourseSettingVo> pageList(ProductCourseSettingPageQuery query) {
        List<TProductCourseSetting> productCourseSettings=baseMapper.selectProductCourseSettingByQuery(query);
        return BeanUtil.copyToList(productCourseSettings,ProductCourseSettingVo.class);
    }

    @Override
    public ProductSettingDto getProductCourseSetting(Long productId){
        Date now=new Date();
        List<TProductCourseSetting> tProductCourseSetting=baseMapper.selectList(
                new LambdaQueryWrapper<TProductCourseSetting>().eq(TProductCourseSetting::getProductId,productId)
                        .eq(TProductCourseSetting::getDataStatus,1)
                        .le(TProductCourseSetting::getCorpStartTime,now)
                        .ge(TProductCourseSetting::getCorpEndTime,now)
        );
        return CollUtil.isNotEmpty(tProductCourseSetting) ?
                ProductSettingDto.builder()
                        .productId(tProductCourseSetting.getFirst().getProductId())
                        .unitPayDay(tProductCourseSetting.getFirst().getUnitPayDay())
                        .productType(tProductCourseSetting.getFirst().getProductType())
                        .refThirdId(tProductCourseSetting.getFirst().getRefThirdId())
                        .build():null;
    }

    @Override
    public Map<Long,ProductPropertyDto> loadProductCourseSettingByOrderDto(PayOrderInfoDto payOrderInfoDto) {
        Map<Long,ProductPropertyDto> productPropertyDtoMap=new HashMap<>();
        if (payOrderInfoDto!=null) {
            if (CollUtil.isNotEmpty(payOrderInfoDto.getOrderItemInfos())) {
                List<String> courseDataIds = payOrderInfoDto.getOrderItemInfos().stream().map(PayOrderItemInfoDto::getProductId).toList();
                Date now = new Date();
                List<TProductCourseSetting> tProductCourseSettings = baseMapper.selectList(
                        new LambdaQueryWrapper<TProductCourseSetting>()
                                .in(TProductCourseSetting::getProductId, courseDataIds)
                                .eq(TProductCourseSetting::getDataStatus, 1)
                                .le(TProductCourseSetting::getCorpStartTime, now)
                                .ge(TProductCourseSetting::getCorpEndTime, now)
                                .orderByDesc(TProductCourseSetting::getCorpEndTime)
                );
                Map<Long, TProductCourseSetting> productCourseSettingMap = tProductCourseSettings.stream().collect(Collectors.toMap(TProductCourseSetting::getProductId,
                        Function.identity(), (a1, a2) -> a1));

                //聚合产品分别查询产品属性信息，默认的是课程产品
                payOrderInfoDto.getOrderItemInfos().forEach(orderItemInfo -> {
                    if (productCourseSettingMap.containsKey(Long.valueOf(orderItemInfo.getProductId()))) {
                        TProductCourseSetting productCourseSetting = productCourseSettingMap.get(Long.valueOf(orderItemInfo.getProductId()));
                        if (ContentProductTypeDefine.COURSE_GK.name().equals(productCourseSetting.getProductType())){
                            ProductPropertyDto productPropertyDto= ProductPropertyDto.buildGklCourse(Long.valueOf(orderItemInfo.getProductId()), orderItemInfo.getProductName(),productCourseSetting.getUnitPayDay());
                            ProductSettingDto productSettingDto=productPropertyDto.getCourseProductSettingDto();
                            productSettingDto.setUnitPayDay(productCourseSetting.getUnitPayDay());
                            productSettingDto.setRefThirdId(productCourseSetting.getRefThirdId());
                            productPropertyDtoMap.put(Long.valueOf(orderItemInfo.getProductId()), productPropertyDto);
                        }else {
                            ProductPropertyDto productPropertyDto= ProductPropertyDto.buildLocalCourse(Long.valueOf(orderItemInfo.getProductId()), orderItemInfo.getProductName());
                            productPropertyDtoMap.put(Long.valueOf(orderItemInfo.getProductId()), productPropertyDto);
                        }
                    } else {
                        ProductPropertyDto productPropertyDto= ProductPropertyDto.buildLocalCourse(Long.valueOf(orderItemInfo.getProductId()), orderItemInfo.getProductName());
                        productPropertyDtoMap.put(Long.valueOf(orderItemInfo.getProductId()), productPropertyDto);
                        //有组合的话，这里可以也放判断子订单的产品类型，但目前子订单没有类型
                       //TODO: 如果订单是组合的话，这里可以判断子订单的产品类型，但目前子订单没有类型
                    }
                });

            }else {
                if (ContentProductTypeDefine.PRODUCT_THIRD_CAP.name().equals(payOrderInfoDto.getProductType())) {
                    //高考志愿的没子订单
                    productPropertyDtoMap.put(Long.valueOf(payOrderInfoDto.getProductId()), ProductPropertyDto.buildCAP(Long.valueOf(payOrderInfoDto.getProductId()), payOrderInfoDto.getProductName()));
                } else if (ContentProductTypeDefine.PRODUCT_THIRD_YCBDC.name().equals(payOrderInfoDto.getProductType())) {
                    //忆成的没子订单
                    productPropertyDtoMap.put(Long.valueOf(payOrderInfoDto.getProductId()), ProductPropertyDto.buildThirdYcbdc(Long.valueOf(payOrderInfoDto.getProductId()), payOrderInfoDto.getProductName()));
                } else {
                    //如果是课程，赶考没配也算本地课程
                    productPropertyDtoMap.put(Long.valueOf(payOrderInfoDto.getProductId()), ProductPropertyDto.buildLocalCourse(Long.valueOf(payOrderInfoDto.getProductId()), payOrderInfoDto.getProductName()));
                }
            }
        }
        return productPropertyDtoMap;
    }

    @Override
    public TransResult<String> deleteProductCourseSetting(ProductCourseSettingDeleteDto productCourseSettingDeleteDto) {
        TProductCourseSetting productCourseSetting =getById(productCourseSettingDeleteDto.getId());
        productCourseSetting.setDataStatus(2);
        updateById(productCourseSetting);
        return TransResult.success();
    }

    @Override
    public List<ProductCourseSettingVo> queryForCourse(Long productId) {
        List<TProductCourseSetting> tProductCourseSettings = baseMapper.selectListByCourseId(productId);
        return CollUtil.isNotEmpty(tProductCourseSettings)?BeanUtil.copyToList(tProductCourseSettings, ProductCourseSettingVo.class):List.of();
    }

    @Override
    public List<ProductCourseSettingVo> queryForLesson(Long productId, List<Long> sectionIds) {
        List<TProductCourseSetting> tProductCourseSettings = baseMapper.selectListByLessonId(productId,sectionIds);
        return CollUtil.isNotEmpty(tProductCourseSettings)?BeanUtil.copyToList(tProductCourseSettings, ProductCourseSettingVo.class):List.of();
    }

    @Override
    public List<ProductCourseSettingVo> queryForSection(Long productId) {
        List<TProductCourseSetting> tProductCourseSettings = baseMapper.selectList(
                Wrappers.lambdaQuery(TProductCourseSetting.class)
                        .eq(TProductCourseSetting::getDataStatus,1).eq(TProductCourseSetting::getProductId,productId).orderByAsc(TProductCourseSetting::getCorpStartTime));
        return CollUtil.isNotEmpty(tProductCourseSettings)?BeanUtil.copyToList(tProductCourseSettings, ProductCourseSettingVo.class):List.of();

    }
}